using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Qibla.Library;
using Microsoft.WindowsMobile.Samples.Location;

namespace Qibla
{
    public partial class QiblaForm : Form
    {
        private const int REFRESH_INTERVAL = 500;
        QiblaLib _lib;
        DateTime _startTime;

        Gps _gps;
        EventHandler _updateDataHandler;
        GpsDeviceState _device = null;
        GpsPosition _position = null;
        PointD _currentPosition;

        PointD _startGps;
        PointD _endGps;

        bool _scanStarted = false;
        
 
        public QiblaForm()
        {
           
            _lib = new QiblaLib();
            _gps = new Gps();
            InitializeComponent();
        }

        /// <summary>
        /// Menu event handler to start listening for gps coordinates
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void mnuGPSReading_Click(object sender, EventArgs e)
        {
            if (!_scanStarted)
            {
                StartGps();

                timerGpsWait.Enabled = true;
                timerGpsWait.Interval = REFRESH_INTERVAL;
                _scanStarted = true;
            }
            else
            {
                StopGps();

                timerGpsWait.Enabled = false;
                _scanStarted = false;
            }
        }


        private void GetCompass(float heading, PointD position)
        {
            pbCompass.Image.Dispose();
            Image img = _lib.DrawCompass(
                pbCompass.Height, pbCompass.Width,
                heading,
                position);

            pbCompass.Image = img;
        }

        private void mnuInformation_Click(object sender, EventArgs e)
        {
            InformationForm infForm = new InformationForm();
            infForm.Show();            
        }

        private void mnuExit_Click(object sender, EventArgs e)
        {
            StopGps();
            Application.Exit();
        }

        private void QiblaForm_Load(object sender, EventArgs e)
        {
            this.Text = Strings.Name;

            pbCompass.Image = _lib.GetBlankGrid(pbCompass.Height,
                pbCompass.Width);
            mnuGPSReading.Text = Strings.StartScan;

            _updateDataHandler = new EventHandler(UpdateData);
            _gps.DeviceStateChanged += new DeviceStateChangedEventHandler(gps_DeviceStateChanged);
            _gps.LocationChanged += new LocationChangedEventHandler(gps_LocationChanged);
                        
        }


        protected void gps_LocationChanged(object sender, LocationChangedEventArgs args)
        {
            _position = args.Position;
            
            // call the UpdateData method via the updateDataHandler so that we
            // update the UI on the UI thread
            BeginInvoke(_updateDataHandler);
        }

        void gps_DeviceStateChanged(object sender, DeviceStateChangedEventArgs args)
        {
            _device = args.DeviceState;
                        
            // call the UpdateData method via the updateDataHandler so that we
            // update the UI on the UI thread
            BeginInvoke(_updateDataHandler);
        }


        /// <summary>
        /// GPS Location change update event handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        void UpdateData(object sender, System.EventArgs args)
        {
            string satteliteData = "";
            double longitude = 0; 
            double lattitude = 0; 
            double numberOfSats = 0;
            double numberOfSatsInView = 0;

            try
            {
                if (_device != null)
                {
                    satteliteData = "GPS Reciever: " + _device.FriendlyName + " " + _device.ServiceState + ", " + _device.DeviceState + "\n";
                }

                // Get GPS data
                if (_gps.Opened)
                {
                    if (_position != null)
                    {
                        satteliteData += DateTime.Now.ToLongTimeString() + "\n";
                        satteliteData += _position.Time + "\n";
                        satteliteData += _position.SatelliteCount + "/" + _position.SatellitesInViewCount + "\n";

                        if (_position.LatitudeValid)
                        {
                            lattitude = _position.GLattitude; 
                            satteliteData += "Latitude :\n   " + _position.GLattitude + "\n";
                        }

                        if (_position.LongitudeValid)
                        {
                            longitude = _position.GLongitude;
                            satteliteData += "Longitude :\n   " + _position.GLongitude + "\n";
                        }
                        satteliteData += "Direction : " + _position.Heading + "\n";

                       // if (_position.HeadingValid)
                        
                            _currentPosition = new PointD(_position.GLongitude,
                                _position.GLattitude);
                        if (_position.HeadingValid)
                        {
                            _currentPosition.Heading = _position.Heading;
                        }
                    }                    
                }
                lblSatteliteData.Text = satteliteData;    
                
            }
            catch
                (OverflowException oex)
            {
                StopGps();
                lblSatteliteData.Text = string.Format(Strings.Error_InvalidGps,
                    lattitude,
                    longitude);
            }
            catch (Exception e)
            {
                //StopGps();
                lblSatteliteData.Visible = true;
                lblSatteliteData.Text = e.ToString();                
            }
        }

        /// <summary>
        /// Time out event handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timer_Tick(object sender, EventArgs e)
        {
            try
            {
                if (_currentPosition != null)
                {
                    GetCompass(_currentPosition.Heading, _currentPosition);
                }
            }
            catch (Exception ex)
            {
                StopGps();
                lblSatteliteData.Text = string.Format(
                    "Current position null={0}\r\nCurrent Position={1}\\Heading={2}\r\nexception={3}",
                    (_currentPosition == null).ToString(),
                    _currentPosition.ToString(),
                    _currentPosition.Heading,
                    ex.Message);
                lblSatteliteData.Visible = true;
            }
        }

        private void mnuAbout_Click(object sender, EventArgs e)
        {
            AboutForm af = new AboutForm();
            af.ShowDialog();
            af.Close();

        }

        /// <summary>
        /// Starts the GPS reciever
        /// </summary>
        private void StartGps()
        {
            if (!_gps.Opened)
            {
                _gps.Open();
            }

            _startTime = DateTime.Now;
            mnuGPSReading.Text = Strings.StopScan;
            mnuGPSReading.Enabled = true;
            mnuStopGps.Enabled = true;
        }

        /// <summary>
        /// Stops the GPS reciever
        /// </summary>
        private void StopGps()
        {
            if (_gps.Opened)
            {
                _gps.Close();
                
                timerGpsWait.Enabled = false;

                mnuGPSReading.Text = Strings.StartScan;
                mnuGPSReading.Enabled = true;
                mnuStopGps.Enabled = false;
            }
        }

        /// <summary>
        /// Stops the GPS reciever
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void mnuStopGps_Click(object sender, EventArgs e)
        {
            StopGps();
        }

        /// <summary>
        /// Used to manually enter coordinates
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void mnuEnterCoordinates_Click(object sender, EventArgs e)
        {
            try
            {
                EnterCoordinatesFrm coordinateForm = new EnterCoordinatesFrm();
                coordinateForm.ShowDialog();
                if (coordinateForm.DialogResult == DialogResult.OK)
                {
                    _startGps = coordinateForm.StartCoordinate;
                    _endGps = coordinateForm.EndCoordinate;
                    GetCompass();
                }
            }
            catch
                (OverflowException oex)
            {
                StopGps();
                lblSatteliteData.Text = Strings.Error_InvalidGps;
            }
            catch (Exception ex)
            {
                StopGps();
                lblSatteliteData.Visible = true;
                lblSatteliteData.Text = ex.ToString();
            }
        }

        private void GetCompass()
        {
            Image img = _lib.DrawCompass(
                pbCompass.Height, pbCompass.Width,
                _startGps,
                _endGps);

            pbCompass.Image = img;
        }


        private void QiblaForm_KeyDown(object sender, KeyEventArgs e)
        {
            if ((e.KeyCode == System.Windows.Forms.Keys.Up))
            {
               // StartGps();
                mnuGPSReading_Click(this, new EventArgs());
            }
            if ((e.KeyCode == System.Windows.Forms.Keys.Down))
            {
                StopGps();
            }
            if ((e.KeyCode == System.Windows.Forms.Keys.Left))
            {
                // Left
                lblSatteliteData.Visible = !lblSatteliteData.Visible;
            }
            if ((e.KeyCode == System.Windows.Forms.Keys.Right))
            {
                // Right
            }
            if ((e.KeyCode == System.Windows.Forms.Keys.Enter))
            {
                mnuGPSReading_Click(this, new EventArgs());
            }
        }

        private void QiblaForm_Closing(object sender, CancelEventArgs e)
        {
            pbCompass.Image.Dispose();
        }
    }
}


//// Unused code

//    satteliteData += DateTime.Now.Ticks + "\n";
//    if (_gps.Opened)
//    {
//        satteliteData += "GPS Reciever Opened \n";

//        if (position != null)
//        {
//            satteliteData += position.Time + "\n";
//            satteliteData += position.SatelliteCount + "\n";
//            satteliteData += position.SatellitesInViewCount + "\n";
//            //satteliteData += "Position recieved \n";
//            //if (position.SatellitesInSolutionValid &&
//            //    position.SatellitesInViewValid &&
//            //    position.SatelliteCountValid)
//            //{
//            //    satteliteData += "Sattelites Valid \n";

//            //    double satteliteRatio = position.GetSatellitesInSolution().Length /
//            //        position.GetSatellitesInView().Length;

//            //    satteliteData += "Number of Sattelites: " + position.SatelliteCount + "\n";
//            //    satteliteData += "Sattelite Ratio: " + satteliteRatio +
//            //        "(" + position.GetSatellitesInSolution().Length + "/" +
//            //         position.GetSatellitesInView().Length + ")\n";

//            //    if (position.SatelliteCount >= 3)
//            //    {
//            float tempRatio;
//            if (_coordinateToRetrieve == CoordianteToRetrieve.Start)
//            {
//                tempRatio = position.SatelliteCount /
//                    position.SatellitesInViewCount;
//                mnuMenu.Text = tempRatio.ToString();

//                if (tempRatio > _satRatio)
//                {
//                    _startGps = new PointD();
//                    if (position.LatitudeValid)
//                    {
//                        _startGps.Y = position.GLattitude;
//                    }

//                    if (position.LongitudeValid)
//                    {
//                        _startGps.X = position.GLongitude;
//                    }

//                    _satRatio = tempRatio;

//                    if (_satRatio > 0.55)
//                    {
//                        mnuGPSReading.Enabled = true;
//                        mnuGPSReading.Text = TXT_END_POS;

//                        _coordinateToRetrieve = CoordianteToRetrieve.End;

//                        _gps.Close();
//                        lblSatteliteData.Visible = false;
//                    }
//                }
//                return;
//            }
//            if (_coordinateToRetrieve == CoordianteToRetrieve.End) 
//            {
//                tempRatio = position.SatelliteCount /
//                    position.SatellitesInViewCount;


//                if (tempRatio > _satRatio)
//                {
//                    _endGps = new PointD();
//                    if (position.LatitudeValid)
//                    {
//                        _endGps.Y = position.GLattitude;
//                    }

//                    if (position.LongitudeValid)
//                    {
//                        _endGps.X = position.GLongitude;
//                    }

//                    _satRatio = tempRatio;
//                }

//                if (_satRatio > 0.55)
//                {
//                    mnuGPSReading.Enabled = true;
//                    mnuGPSReading.Text = TXT_STRT_POS;

//                    _coordinateToRetrieve = CoordianteToRetrieve.Start;

//                    _gps.Close();
//                    lblSatteliteData.Visible = false;

//                    GetCompass();
//                }
//            }

//        }
//    }
//if (_position.SatellitesInViewValid &&
//_position.SatelliteCountValid)
//{
//    numberOfSats = _position.SatelliteCount;
//    numberOfSatsInView = _position.SatellitesInViewCount;

//    satteliteData += "Number of Sats " + numberOfSats + "\n";
//    satteliteData += "Number of Sats in View " + numberOfSatsInView + "\n";                
//}
//lblSatteliteData.Text = satteliteData;
//if (!_inspectSattelites)
//{
//    // Package the retrieved data and send it to the main coordinate processing function
//    CoordinateRecievedArg ce = new CoordinateRecievedArg();
//    ce.Lattitude = lattitude;
//    ce.Longitude = longitude;
//    ce.NumberOfSattelites = numberOfSats;
//    ce.NumberOfSattelitesInView = numberOfSatsInView;


//    CoordinatesProcessor(ce);
//    //this.Invoke(coordinateRcvdDelegate, ce);
//}
//        PointD _endGps;
//        private const int TIMEOUT = 120;
//         bool _inspectSattelites = false;
        //double _satRatio;

/*

        public void CoordinatesProcessor(CoordinateRecievedArg ce)
        {

            try
            {
                if (ce.NumberOfSattelites >= 3)
                {

                    double tempRatio;
                    if (_coordinateToRetrieve == CoordianteToRetrieve.Start)
                    {
                        tempRatio = ce.SatteliteRatio;

                        if (tempRatio > _satRatio)
                        {
                            _startGps = new PointD();
                            _startGps.Y = ce.Lattitude;
                            _startGps.X = ce.Longitude;

                            _satRatio = tempRatio;

                            if (_satRatio > 0.55)
                            {
                                mnuGPSReading.Enabled = true;
                                mnuGPSReading.Text = Strings.GetEndPosition;
                                timerGpsWait.Enabled = false;

                                _coordinateToRetrieve = CoordianteToRetrieve.End;

                                lblSatteliteData.Visible = false;
                                StopGps();

                            }
                        }
                        return;
                    }
                    if (_coordinateToRetrieve == CoordianteToRetrieve.End)
                    {
                        tempRatio = ce.SatteliteRatio;


                        if (tempRatio > _satRatio)
                        {
                            _endGps = new PointD();

                            _endGps.Y = ce.Lattitude;
                            _endGps.X = ce.Longitude;

                            _satRatio = tempRatio;
                        }

                        if (_satRatio > 0.55)
                        {
                            mnuGPSReading.Enabled = true;
                            mnuGPSReading.Text = Strings.GetStartPosition;
                            timerGpsWait.Enabled = false;

                            _coordinateToRetrieve = CoordianteToRetrieve.Start;

                            lblSatteliteData.Visible = false;
                            //StopGps();

                            GetCompass();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw;
            }            
        }
        enum CoordianteToRetrieve {Start, End};
        CoordianteToRetrieve _coordinateToRetrieve;
 _coordinateToRetrieve = CoordianteToRetrieve.Start;
 * 
 *         private void GetCompass()
        {
            Image img = _lib.DrawCompass(
                pbCompass.Height, pbCompass.Width,
                _startGps,
                _endGps);

            pbCompass.Image = img;
        }

 *                 switch (_coordinateToRetrieve)
                {
                    case CoordianteToRetrieve.Start:
                        mnuGPSReading.Text = Strings.GetStartPosition;
                        break;
                    case CoordianteToRetrieve.End:
                        mnuGPSReading.Text = Strings.GetEndPosition;
                        break;
                }
*/